package com.imooc.uaa.domain;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@NoArgsConstructor
@AllArgsConstructor
@Builder
@With
@Data
@Entity
@Table(name = "mooc_users")
public class User implements UserDetails, Serializable {
    /**
     * 自增长 ID，唯一标识
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(length = 50, unique = true, nullable = false)
    private String username;
    @JsonIgnore
    @Column(name = "password_hash", length = 80, nullable = false)
    private String password;
    @Column(length = 11, nullable = false)
    private String mobile;
    @Column(nullable = false, unique = true)
    private String email;
    @Column(length = 50)
    private String name;
    @Column(nullable = false)
    private boolean enabled;
    /**
     * 账户过期
     */
    @Column(name = "account_non_expired", nullable = false)
    private boolean accountNonExpired;
    /**
     * 账户锁定
     */
    @Column(name = "account_non_locked", nullable = false)
    private boolean accountNonLocked;
    /**
     * 密码过期
     */
    @Column(name = "credentials_non_expired")
    private boolean credentialsNonExpired;
    /**
     * 是否启用两步验证
     */
    @Builder.Default
    @Column(name = "using_mfa", nullable = false)
    private boolean usingMfa = false;
    /**
     * 两步验证的key
     */
    @JsonIgnore
    @Column(name = "mfa_key")
    private String mfaKey;
    @ManyToMany
    @Fetch(FetchMode.JOIN)
    @JoinTable(
            name = "mooc_users_roles",
            joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")})
    private Set<Role> roles;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return roles.stream().flatMap(role -> Stream.concat(
                Stream.of(new SimpleGrantedAuthority(role.getRoleName())),
                role.getPermissions().stream()
        )).collect(Collectors.toList());
    }
}
